﻿using DimensionsHelper.LanguageService.Syntax;

namespace DimensionsHelper.LanguageService.Symbols;

/// <summary>
///     函数或属性的参数符号。
/// </summary>
public class ParameterSymbol : BindableSymbol
{
    internal ParameterSymbol(ParameterSignature declaration, ITypeSymbol containingSymbol) :
        base(SymbolKinds.Parameter, declaration, containingSymbol, null)
    {
        IsOptional = declaration.OptionalKeywordToken != null;
        IsParamArray = declaration.ParamArrayKeywordToken != null;
        UpdateCachedBinding(ValueTypeSymbol.Any);
    }


    internal ParameterSymbol(VariableDeclaration declaration, ITypeSymbol containingSymbol) :
        base(SymbolKinds.Parameter, declaration, containingSymbol, null)
    {
        if (declaration is not { Kind: SyntaxKinds.ArrayDeclaration })
        {
            UpdateCachedBinding(ValueTypeSymbol.Any);
            return;
        }

        // 本地函数的参数定义节点为本地变量声明—— Variable, Array[]，如果参数声明为数组，
        // 需要预先绑定一个Any[]类型的数组类型。
        ArrayDeclaration arrDecl = (ArrayDeclaration)declaration;
        int[] bounds = new int[arrDecl.Rank];
        for (int i = 0; i < arrDecl.Rank; i++)
        {
            IntegerLiteral? declareBound = arrDecl.GetBoundary(i + 1);
            bounds[i] = declareBound?.Value ?? -1;
        }

        UpdateCachedBinding(ValueTypeSymbol.Any.MakeArrayType(arrDecl.Rank, bounds));
    }


    public override ModuleSymbol? ContainingModule =>
        ContainingSymbol?.ContainingModule as ModuleSymbol;


    public override bool CanMakeArray => false;


    public override bool IsParameter => true;


    /// <summary>
    ///     如果参数带有Optional修饰符，返回<see langword="true" />。
    ///     表示此参数是可选参数，允许忽略或者接收空白参数。
    /// </summary>
    public bool IsOptional { get; }


    /// <summary>
    ///     如果参数带有ParamArray修饰符，返回<see langword="true" />。
    ///     表示此参数是可变参数，可以接收0或多个同类型参数。
    /// </summary>
    public bool IsParamArray { get; }
}